package day23.collection;

import java.util.*;

// 实现Comparable接口的Student类，支持自然排序
class Student implements Comparable<Student> {
    private String name;
    private int age;
    private double score;
    
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    public double getScore() {
        return score;
    }
    
    // 自然排序：按分数从高到低排序
    // 实现Comparable接口的compareTo方法，定义对象的自然排序规则
    // 返回负数表示当前对象小于参数对象，0表示相等，正数表示当前对象大于参数对象
    @Override
    public int compareTo(Student other) {
        // 使用Double.compare方法比较分数，other.score在前表示降序排列
        return Double.compare(other.score, this.score);
    }
    
    @Override
    public String toString() {
        return String.format("Student{name='%s', age=%d, score=%.1f}", name, age, score);
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Student student = (Student) obj;
        return age == student.age && Double.compare(student.score, score) == 0 && Objects.equals(name, student.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, age, score);
    }
}

public class SortTest {
    public static void main(String[] args) {
        // 创建学生列表，用于演示各种排序方法
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 20, 85.5));
        students.add(new Student("Bob", 22, 92.0));
        students.add(new Student("Charlie", 21, 78.5));
        students.add(new Student("David", 23, 92.0));
        students.add(new Student("Eve", 19, 88.0));
        
        System.out.println("=== 原始列表 ===");
        students.forEach(System.out::println);
        
        // 自然排序测试（使用Comparable接口）
        // 调用Collections.sort()方法，使用Student类中定义的compareTo方法进行排序
        System.out.println("\n=== 自然排序（按分数降序） ===");
        Collections.sort(students);  // 使用自然排序
        students.forEach(System.out::println);
        
        // 重新打乱列表，使用Collections.shuffle方法随机打乱列表顺序
        Collections.shuffle(students);
        System.out.println("\n=== 重新打乱后的列表 ===");
        students.forEach(System.out::println);
        
        // 使用比较器按年龄排序
        // Comparator.comparing方法创建一个按age字段排序的比较器
        System.out.println("\n=== 使用比较器按年龄升序排序 ===");
        students.sort(Comparator.comparing(Student::getAge));
        students.forEach(System.out::println);
        
        // 使用比较器按姓名排序
        // 再次打乱列表以便观察排序效果
        Collections.shuffle(students);
        System.out.println("\n=== 重新打乱后的列表 ===");
        students.forEach(System.out::println);
        
        System.out.println("\n=== 使用比较器按姓名排序 ===");
        // Comparator.comparing方法创建一个按name字段排序的比较器
        students.sort(Comparator.comparing(Student::getName));
        students.forEach(System.out::println);
        
        // 使用比较器按分数升序排序
        Collections.shuffle(students);
        System.out.println("\n=== 重新打乱后的列表 ===");
        students.forEach(System.out::println);
        
        System.out.println("\n=== 使用比较器按分数升序排序 ===");
        // Comparator.comparing方法创建一个按score字段排序的比较器（默认升序）
        students.sort(Comparator.comparing(Student::getScore));
        students.forEach(System.out::println);
        
        // 使用比较器按分数降序排序
        System.out.println("\n=== 使用比较器按分数降序排序 ===");
        // 使用reversed()方法将比较器的排序顺序颠倒，实现降序排序
        students.sort(Comparator.comparing(Student::getScore).reversed());
        students.forEach(System.out::println);
        
        // 多级排序：先按分数降序，再按年龄升序
        Collections.shuffle(students);
        System.out.println("\n=== 重新打乱后的列表 ===");
        students.forEach(System.out::println);
        
        System.out.println("\n=== 多级排序：按分数降序，再按年龄升序 ===");
        // 使用thenComparing方法实现多级排序：
        // 首先按分数降序排序，分数相同时按年龄升序排序
        students.sort(Comparator.comparing(Student::getScore).reversed()
                                .thenComparing(Student::getAge));
        students.forEach(System.out::println);
        
        // 使用TreeSet进行自然排序
        // TreeSet是一个有序集合，插入元素时会自动排序
        // 不提供比较器时使用元素的自然排序（即compareTo方法）
        System.out.println("\n=== TreeSet自然排序（按分数降序） ===");
        TreeSet<Student> treeSetNatural = new TreeSet<>();
        treeSetNatural.add(new Student("Alice", 20, 85.5));
        treeSetNatural.add(new Student("Bob", 22, 92.0));
        treeSetNatural.add(new Student("Charlie", 21, 78.5));
        treeSetNatural.add(new Student("David", 23, 92.0));
        treeSetNatural.add(new Student("Eve", 19, 88.0));
        treeSetNatural.forEach(System.out::println);
        
        // 使用TreeSet和自定义比较器
        // 提供自定义比较器，TreeSet将使用该比较器进行排序而不是自然排序
        System.out.println("\n=== TreeSet使用比较器排序（按姓名） ===");
        TreeSet<Student> treeSetComparator = new TreeSet<>(Comparator.comparing(Student::getName));
        treeSetComparator.addAll(treeSetNatural);
        treeSetComparator.forEach(System.out::println);
        
        // 测试数组排序
        System.out.println("\n=== 数组排序测试 ===");
        Student[] studentArray = {
            new Student("Alice", 20, 85.5),
            new Student("Bob", 22, 92.0),
            new Student("Charlie", 21, 78.5)
        };
        
        System.out.println("排序前:");
        Arrays.stream(studentArray).forEach(System.out::println);
        
        System.out.println("使用自然排序（按分数降序）:");
        // 使用Arrays.sort()对数组进行排序，不提供比较器时使用自然排序
        Arrays.sort(studentArray);
        Arrays.stream(studentArray).forEach(System.out::println);
        
        System.out.println("使用比较器按年龄排序:");
        // 使用Arrays.sort()对数组进行排序，提供比较器实现自定义排序
        Arrays.sort(studentArray, Comparator.comparing(Student::getAge));
        Arrays.stream(studentArray).forEach(System.out::println);
    }
}